package ast;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import scanner.TokenType;
import ast.nodes.ProgramNode;

public class ASTTree {
    private ASTNode root;
    private Evaluation eval = null;
    private boolean showDFA = false, showNFA = false, showDebug = false;
    
    public boolean isShowDFA() {
		return showDFA;
	}

	public void setShowDFA(boolean showDFA) {
		this.showDFA = showDFA;
		if(eval != null)
			eval.setShowDFA(showDFA);
	}

	public boolean isShowNFA() {
		return showNFA;
	}

	public void setShowNFA(boolean showNFA) {
		this.showNFA = showNFA;
		if(eval != null)
			eval.setShowNFA(showNFA);
	}

	public boolean isShowDebug() {
		return showDebug;
	}

	public void setShowDebug(boolean showDebug) {
		this.showDebug = showDebug;
		if(eval != null)
			eval.setShowDebug(showDebug);
	}

	public ASTTree() {
        root = new ProgramNode();
    }

    public ASTNode getRoot() {
        return root;
    }

    public void setRoot(ASTNode root) {
        this.root = root;
    }

    // Displays the tree
    public String toString() {
    	compress();
        return "AST:" + root.toString(0);
    }

    public String getInput()
    {
        return eval.getInput();
    }
    
    public String getOutput()
    {
        return eval.getOutput();
    }
    
    // Runs
    public void run(String input) throws Exception {
        eval = new Evaluation(input);
        eval.setShowDebug(showDebug);
        eval.setShowDFA(showDFA);
        eval.setShowNFA(showNFA);
        this.root.run(eval);
    }
    
    public void run(File input) throws Exception
    {
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                new FileInputStream(input))); 
        StringBuffer app = new StringBuffer();
        String line;
        while((line = reader.readLine()) != null)
            app.append(line + "\n");
        run(app.toString());
    } 
    
    // Compress - Remove ConcatNode if it only has one child
    public void compress() {
    	ASTNode curr = root;
    	performCompression(curr);
    }

    private void performCompression(ASTNode currentNode) {
    	if ((currentNode.getData() != null) && currentNode.getData().getType().equals(TokenType.CONCAT) && (currentNode.getChildren().size() == 1)) {
    		currentNode.setData(currentNode.getChildren().get(0).getData());
    		currentNode.setChildren(currentNode.getChildren().get(0).getChildren());
    	}
    	else
    		for (ASTNode child : currentNode.getChildren())
    			performCompression(child);
    }
}
